////////////////////////////////////////////
// 这里实现标签页的切换
////////////////////////////////////////////

function initSwitchTab() {
    // 1. 先获取到相关的元素(标签页的按钮, 会话列表, 好友列表)
    let tabSession = document.querySelector('.tab .tab-session');
    let tabFriend = document.querySelector('.tab .tab-friend');
    // querySelectorAll 可以同时选中多个元素. 得到的结果是个数组
    // [0] 就是会话列表
    // [1] 就是好友列表
    let lists = document.querySelectorAll('.list');
    // 2. 针对标签页按钮, 注册点击事件. 
    //    如果是点击 会话标签按钮, 就把会话标签按钮的背景图片进行设置. 
    //    同时把会话列表显示出来, 把好友列表隐藏
    //    如果是点击 好友标签按钮, 就把好友标签按钮的背景图片进行设置. 
    //    同时把好友列表显示出来, 把会话列表进行隐藏
    tabSession.onclick = function() {
        // a) 设置图标
        tabSession.style.backgroundImage = 'url(img/对话.png)';
        tabFriend.style.backgroundImage = 'url(img/用户2.png)';
        // b) 让会话列表显示出来, 让好友列表进行隐藏
        lists[0].classList = 'list';
        lists[1].classList = 'list hide';
    }

    tabFriend.onclick = function() {
        // a) 设置图标
        tabSession.style.backgroundImage = 'url(img/对话2.png)';
        tabFriend.style.backgroundImage = 'url(img/用户.png)'
        // b) 让好友列表显示, 让会话列表隐藏
        lists[0].classList = 'list hide';
        lists[1].classList = 'list';
    }
}

initSwitchTab();

/////////////////////////////////////////////////////
// 操作 websocket
/////////////////////////////////////////////////////

// 创建 websocket 实例
let websocket = new WebSocket("ws://" + location.host + "/ws?userToken=" + localStorage.getItem("userToken"));

websocket.onopen = function() {
    console.log("websocket 连接成功!");
}

websocket.onmessage = function(e) {
    console.log("websocket 收到消息! " + e.data);
    // 此时收到的 e.data 是个 json 字符串, 需要转成 js 对象
    let resp = JSON.parse(e.data);
    if (resp.type == 'message') {
        // 处理消息响应
        handleMessage(resp);
    } else if (resp.type == 'addFriendRequest') {
        // 处理添加好友请求
        handleAddFriend(resp);
    } else if (resp.type == 'acceptFriend') {
        // 处理接受好友响应
        handleAcceptFriend(resp);
    } else {
        // resp 的 type 出错!
        console.log("resp.type 不符合要求!");
    }
}

websocket.onclose = function() {
    console.log("websocket 连接关闭!");
}

websocket.onerror = function() {
    console.log("websocket 连接异常!");
}

// 添加好友
function handleAcceptFriend(resp) {
    // 刷新好友列表
    getFriendList(localStorage.getItem("loginUserId"));
    // 提示
    alert(resp.fromUserName + ' 已经通过你的好友申请!');
}

// 发送的添加好友请求
function handleAddFriend(resp) {
    // 在会话列表中新增一项，表示添加好友请求
    addFriendRequest(resp.fromUserId,resp.fromUserName,resp.reason);
}


// 发送的信息
function handleMessage(resp) {
    // 把客户端收到的消息, 给展示出来. 
    // 展示到对应的会话预览区域, 以及右侧消息列表中. 

    // 1. 根据响应中的 sessionId 获取到当前会话对应的 li 标签. 
    //    如果 li 标签不存在, 则创建一个新的
    let curSessionLi = findSessionLi(resp.sessionId);
    if (curSessionLi == null) {
        // 就需要创建出一个新的 li 标签, 表示新会话. 
        curSessionLi = document.createElement('li');
        curSessionLi.setAttribute('message-session-id', resp.sessionId);
        // 此处 p 标签内部应该放消息的预览内容. 一会后面统一完成, 这里先置空
        curSessionLi.innerHTML = '<h3>' + resp.fromName + '</h3>'
            + '<p></p>';
        // 给这个 li 标签也加上点击事件的处理
        curSessionLi.onclick = function() {
            clickSession(curSessionLi);
        }
    }
    // 2. 把新的消息, 显示到会话的预览区域 (li 标签里的 p 标签中)
    //    如果消息太长, 就需要进行截断. 
    let p = curSessionLi.querySelector('p');
    p.innerHTML = resp.content;
    if (p.innerHTML.length > 10) {
        p.innerHTML = p.innerHTML.substring(0, 10) + '...';
    }
    // 3. 把收到消息的会话, 给放到会话列表最上面. 
    let sessionListUL = document.querySelector('#session-list');
    sessionListUL.insertBefore(curSessionLi, sessionListUL.children[0]);
    // 4. 如果当前收到消息的会话处于被选中状态, 则把当前的消息给放到右侧消息列表中. 
    //    新增消息的同时, 注意调整滚动条的位置, 保证新消息虽然在底部, 但是能够被用户直接看到. 
    if (curSessionLi.className == 'selected') {
        // 把消息列表添加一个新消息. 
        let messageShowDiv = document.querySelector('.right .message-show');
        addMessage(messageShowDiv, resp);
        scrollBottom(messageShowDiv);
    }
    // 其他操作, 还可以在会话窗口上给个提示 (红色的数字, 有几条消息未读), 还可以播放个提示音.  
    // 这些操作都是纯前端的. 实现也不难, 不是咱们的重点工作. 暂时不做了. 
}

function findSessionLi(targetSessionId) {
    // 获取到所有的会话列表中的 li 标签
    let sessionLis = document.querySelectorAll('#session-list li');
    for (let li of sessionLis) {
        let sessionId = li.getAttribute('message-session-id');
        if (sessionId == targetSessionId) {
            return li;
        }
    }
    // 啥时候会触发这个操作, 就比如如果当前新的用户直接给当前用户发送消息, 此时没存在现成的 li 标签
    return null;
}

/////////////////////////////////////////////////////
// 实现消息发送/接收逻辑
/////////////////////////////////////////////////////

function initSendButton() {
    // 1. 获取到发送按钮 和 消息输入框
    let sendButton = document.querySelector('.right .ctrl button');
    let messageInput = document.querySelector('.right .message-input');
    // 2. 给发送按钮注册一个点击事件
    sendButton.onclick = function() {
        // a) 先针对输入框的内容做个简单判定. 比如输入框内容为空, 则啥都不干
        if (!messageInput.value) {
            // value 的值是 null 或者 '' 都会触发这个条件
            return;
        }
        // b) 获取当前选中的 li 标签的 sessionId
        let selectedLi = document.querySelector('#session-list .selected');
        if (selectedLi == null) {
            // 当前没有 li 标签被选中. 
            return;
        }
        let sessionId = selectedLi.getAttribute('message-session-id');
        // c) 构造 json 数据
        let req = {
            type: 'message',
            sessionId: sessionId,
            content: messageInput.value
        };
        req = JSON.stringify(req);
        console.log("[websocket] send: " + req);
        // d) 通过 websocket 发送消息
        websocket.send(req);
        // e) 发送完成之后, 清空之前的输入框
        messageInput.value = '';
    }
}

initSendButton();

/////////////////////////////////////////////////////
// 关于添加好友
/////////////////////////////////////////////////////
var id = localStorage.getItem("loginUserId");

// 查找好友
function initFindFriend(id) {
    let search = document.querySelector('.search');
    let input = document.querySelector('.search input');
    let button = document.querySelector('.search button');
    button.onclick = function() {
    // 给服务器发送请求, 获取匹配的好友.
        // 1. 验证输入值
        const nameValue = input.value.trim();
        if (!nameValue) {
            alert("请输入好友名称");
            return;
        }
        
        // 2. 验证用户ID
        if (!id || isNaN(id)) {
            console.error("无效的用户ID:", id);
            alert("用户信息无效，请重新登录");
            return;
        }
        
        // 3. 构建安全的URL
        const encodedName = encodeURIComponent(nameValue);
        const requestUrl = `friend/findFriend?userId=${id}&name=${encodedName}`;
        
        console.log("发送请求:", requestUrl);

        $.ajax({
            type: 'get',
            url: requestUrl,
            success: function(result) {
                if(result != null && result.code == "SUCCESS") {
                    let titleDiv = document.querySelector('.title');
                    titleDiv.innerHTML = '查找结果';
                    let messageShowDiv = document.querySelector('.message-show');
                    messageShowDiv.innerHTML = '';
                    let body = result.data;
                    for (let friend of body) {
                        let itemDiv = document.createElement('div');
                        itemDiv.className = 'message';
                        let span = document.createElement('span');
                        span.innerHTML = friend.friendName;
                        span.setAttribute('friend-id', friend.friendId);
                        let input = document.createElement('input');
                        input.type = 'text';
                        input.placeholder = '添加好友理由';
                        let button = document.createElement('button');
                        button.innerHTML = '+';
                        button.onclick = function() {
                            sendAddFriend(friend.friendId, input.value);
                        }
                        itemDiv.appendChild(span);
                        itemDiv.appendChild(input);
                        itemDiv.appendChild(button);
                        messageShowDiv.appendChild(itemDiv);
                    }
                }
            },
            error: function() {
                alert('查找好友失败! name=' + input.value.trim());
            }
        })
    }
}
initFindFriend(id);

// 发送添加好友的信息
function sendAddFriend(friendId, reason) {
    // friendId 朋友ID
    // reason 发送的请求说明
    $.ajax({
        type: 'get',
        url: 'friend/addFriend?userId=' + localStorage.getItem("loginUserId") 
        + '&friendId=' + friendId + '&reason=' + encodeURIComponent(reason),
        success: function(result) {
            if(result != null && result.code == "SUCCESS") {
                alert("添加好友的请求已经发送!");
            }else {
                alert("添加好友失败!");
            }
        }
    });
}


$(function() {
    getAddFriendRequest();
});

// 新增一个好友请求项,放到会话列表中
function addFriendRequest(fromUserId, fromUserName, reason) {
    // 检查是否已存在该请求
    if (document.querySelector(`li[from-user-id="${fromUserId}"]`)) {
        return;
    }
    console.log("好友请求响应 fromUserId, fromUserName, reason :", fromUserId, fromUserName, reason);
    let sessionList = document.querySelector('#session-list');
    let li = document.createElement('li');
    li.setAttribute('from-user-id', fromUserId);
    li.style = 'height: 100px';
    let h3 = document.createElement('h3');
    h3.innerHTML = fromUserName;
    let p = document.createElement('p');
    p.innerHTML = reason;
    let rowDiv = document.createElement('div');
    rowDiv.className = 'row';
    let buttonAccept = document.createElement('button');
    buttonAccept.innerHTML = '接受';
    buttonAccept.onclick = function() {
        // 接受按钮的处理
        $.ajax({
            type: 'get',
            url: 'friend/acceptFriend?friendId=' + fromUserId + '&userId=' + localStorage.getItem("loginUserId"),
            success: function() {
                alert("通过 " + fromUserName + " 的好友申请 处理成功!");
                // 刷新好友列表
                getFriendList(localStorage.getItem("loginUserId"));
                // 删除当前的好友请求项
                sessionList.removeChild(li);
            },
            error: function() {
                alert("通过 " + fromUserName + " 的好友申请 处理失败!");
            }
        });
    }
    let buttonReject = document.createElement('button');
    buttonReject.innerHTML = '拒绝';
    buttonReject.onclick = function() {
        // 忽略请求
        $.ajax({
            type: 'get',
            url: 'friend/rejectFriend?friendId=' + fromUserId + '&userId=' + localStorage.getItem("loginUserId"),
            success: function() {
                alert("拒绝 " + fromUserName + " 的好友申请 处理成功!");
                // 删除当前的好友请求项
                sessionList.removeChild(li);
            },
            error: function() {
                alert("拒绝 " + fromUserName + " 的好友申请 处理失败!");
            }
        });

    }
    li.appendChild(h3);
    li.appendChild(p);
    rowDiv.appendChild(buttonAccept);
    rowDiv.appendChild(buttonReject);
    li.appendChild(rowDiv);
    sessionList.insertBefore(li, sessionList.children[0]);
}

// 查询添加好友的信息
function getAddFriendRequest() {
    $.ajax({
        type: 'get',
        url: 'friend/getFriendRequest?userId=' + localStorage.getItem("loginUserId"),
        success: function(result) {
            if(result != null && result.code == "SUCCESS") {
                console.log("好友请求响应:", result);
                let body = result.data;
                for(let item of body) {
                    console.log("好友请求响应:", item);
                    addFriendRequest(item.fromUserId,item.fromUserName,item.reason);
                }
            }
        },
        error: function() {
            alert("加载添加好友请求失败!");
        }
    });
}


/////////////////////////////////////////////////////
// 从服务器获取到用户登录数据
/////////////////////////////////////////////////////

function getUserInfo(id) {
    $.ajax({
        type: "get",
        url: "user/getUserInfo?userId=" + id,
        success: function(result) {
            if(result != null && result.code == "SUCCESS") {
                var userInfo = result.data;
                $(".main .left .user").text(userInfo.username);
            }else {
                alert(result.errMsg);
            }
        }
    });
}

getUserInfo(id);

function getFriendList(id) {
    $.ajax({
        type: "get",
        url: "/friend/friendList?userId=" + id,
        success: function(body) {
            if(body != null && body.code == "SUCCESS") {
                 // 1. 先把之前的好友列表的内容, 给清空
                let friendListUL = document.querySelector('#friend-list');
                friendListUL.innerHTML = '';
                // 2. 遍历 body, 把服务器响应的结果, 加回到当前的 friend-list 中. 
                for (let friend of body.data) {
                    let li = document.createElement('li');
                    li.innerHTML = '<h4>' + friend.friendName + '</h4>';
                    // 此处把 friendId 也记录下来, 以备后用. 
                    // 把 friendId 作为一个 html 的自定义属性, 加到 li 标签上就行了. 
                    li.setAttribute('friend-id', friend.friendId);
                    friendListUL.appendChild(li);
    
                    // 每个 li 标签, 就对应界面上的一个好友的选项. 给这个 li 加上点击事件的处理. 
                    li.onclick = function() {
                        // 参数表示区分了当前用户点击的是哪个好友. 
                        clickFriend(friend);
                    }
                }
            }else {
                alert(body.errMsg);
                return;
            }
        },
        error: function() {
            console.log('获取好友列表失败!');
        }
    });
}

getFriendList(id);

function getSessionList(id) {
    $.ajax({
        type: "get",
        url: "/session/getSessionList?userId=" + id,
        success: function(result) {
            if(result != null && result.code == "SUCCESS") {
                // 1. 清空之前的会话列表
                let sessionListUl = document.querySelector("#session-list");
                sessionListUl.innerHTML = '';
                // 2. 遍历响应的 result.data 的数组，来构造页面
                for(let session of result.data) {
                    // 先针对 session 中的信息进行截断
                    if(session.lastMessage.length > 10) {
                        session.lastMessage = session.lastMessage.substring(0,10) + "...";
                    }

                    let li = document.createElement('li');
                    // 把会话Id 存放到li 的标签的自定义属性中
                    li.setAttribute('message-session-id',session.sessionId);
                    li.innerHTML = '<h3>' + session.friends[0].friendName + '</h3>' 
                                + '<p>' + session.lastMessage + '</p>';
                    sessionListUl.appendChild(li);

                    // 给 li 添加一个点击事件
                    li.onclick = function() {
                        // 这个写法, 就能保证, 点击哪个 li 标签
                        // 此处对应的 clickSession 函数的参数就能拿到哪个 li 标签. 
                        clickSession(li);
                    }
                }
            }else {
                alert(result.errMsg);
            }
        }
    })
}

getSessionList(id);

function clickSession(currentLi) {
    // 1.设置高亮
    //   获取 session-list 下的所有的 li 标签
    let allLis = document.querySelectorAll("#session-list>li");
    //   遍历所有的 li 标签 查看谁和 currentLi 标签是一致的就进行设置高亮
    activeSession(allLis,currentLi);

    // 2.获取指定会话的历史信息
    let sessionId = currentLi.getAttribute("message-session-id");
    getHistoryMessage(sessionId);
}

function activeSession(allLis,currentLi) {
    for(let li of allLis) {
        if (li == currentLi) {
            li.className = 'selected';
        }else {
            li.className = '';
        }
    }
}

// 这个函数负责获取指定会话的历史消息. 
function getHistoryMessage(sessionId) {
    console.log("获取历史消息 sessionId=" + sessionId);
    // 1. 先清空右侧列表中的已有内容
    let titleDiv = document.querySelector('.right .title');
    titleDiv.innerHTML = '';
    let messageShowDiv = document.querySelector('.right .message-show');
    messageShowDiv.innerHTML = '';

    // 2. 重新设置会话的标题. 新的会话标题是点击的那个会话上面显示的标题
    //    先找到当前选中的会话是哪个. 被选中的会话带有 selected 类的. 
    let selectedH3 = document.querySelector('#session-list .selected>h3');
    if (selectedH3) {
        // selectedH3 可能不存在的. 比如页面加载阶段, 可能并没有哪个会话被选中. 
        // 也就没有会话带有 selected 标签. 此时就无法查询出这个 selectedH3
        titleDiv.innerHTML = selectedH3.innerHTML;
    }
    // 3. 发送 ajax 请求给服务器, 获取到该会话的历史消息. 
    $.ajax({
        type: "get",
        url: "/message/getMessage?sessionId=" + sessionId,
        success: function(result) {
            if(result != null && result.code == "SUCCESS") {
                var body = result.data;
                // 此处返回的 body 是个 js 对象数组, 里面的每个元素都是一条消息. 
                // 直接遍历即可. 
                for (let message of body) {
                    addMessage(messageShowDiv, message);
                }
                // 加个操作: 在构造好消息列表之后, 控制滚动条, 自动滚动到最下方. 
                scrollBottom(messageShowDiv);
            }else {
                alert(result.errMsg);
            }
        }
    });
}

function addMessage(messageShowDiv, message) {
    let messageDiv = document.createElement('div');
    let selfUsername = document.querySelector('.left .user').innerHTML;
    
    if (selfUsername == message.fromName) {
        messageDiv.className = 'message message-right';
        messageDiv.innerHTML = '<div class="box">' 
            + '<div class="message-header">'
            + '<span class="post-time">' + message.postTime  + '|' + '</span>'
            + '<span class="username">' + message.fromName + '</span>'
            + '</div>'
            + '<p>' + message.content + '</p>'
            + '</div>';
    } else {
        messageDiv.className = 'message message-left';
        messageDiv.innerHTML = '<div class="box">' 
            + '<div class="message-header">'
            + '<span class="username">' + message.fromName + '</span>'
            + '<span class="post-time">' + '|' + message.postTime + '</span>'
            + '</div>'
            + '<p>' + message.content + '</p>'
            + '</div>';
    }
    messageShowDiv.appendChild(messageDiv);
}

// 把 messageShowDiv 里的内容滚动到底部. 
function scrollBottom(elem) {
    // 1. 获取到可视区域的高度
    let clientHeight = elem.offsetHeight;
    // 2. 获取到内容的总高度
    let scrollHeight = elem.scrollHeight;
    // 3. 进行滚动操作, 第一个参数是水平方向滚动的尺寸. 第二个参数是垂直方向滚动的尺寸
    elem.scrollTo(0, scrollHeight - clientHeight);
}


// 点击好友, 触发的函数
function clickFriend(friend) {
    // 1. 先判定一下当前这个好友是否有对应的会话. 
    //    使用一个单独的函数来实现. 这个函数参数是用户的名字. 返回值是一个 li 标签. 
    //    找到了就是返回了对应会话列表里的 li; 如果没找到, 返回 null
    let sessionLi = findSessionByName(friend.friendName);
    let sessionListUl = document.querySelector("#session-list");
    if(sessionLi) {
        // 2. 存在，会直接将其会话 设置为选中状态，获取历史信息，并置顶
        //    insertBefore 把这个找到的 li放到最前面
        sessionListUl.insertBefore(sessionLi,sessionListUl.children[0]);
        // 这时候就需要将其设置为 选中状态，并且获取历史信息，就可以了
        // 这两个功能在上面的 clickSession 方法已经将其 完成了
        // 直接调用 clickSession 方法即可
        // clickSession(sessionLi);
        // 或者模拟点击
        sessionLi.click();
    }else {
        // 3. 不存在就直接创建一个新的回话 (创建li标签 + 通知服务器)
        sessionLi = document.createElement('li');
        // 构造 li 的内容 ，由于是新的标签，所以这里是没有最后的内容的，直接赋null
        sessionLi.innerHTML = '<h3>' + friend.friendName + '</h3>' + '<p></p>';
        //    把标签进行置顶，并且将其设置成选中状态
        sessionListUl.insertBefore(sessionLi, sessionListUl.children[0]);
        sessionLi.onclick = function() {
            clickSession(sessionLi);
        }
        sessionLi.click();

        //    发送消息给服务器, 告诉服务器当前新创建的会话是啥样的. 
        createSession(friend.friendId, id, sessionLi);
    }
    // 4. 还需要把标签页给切换到 会话列表. 
    //    实现方式很容易, 只要找到会话列表标签页按钮, 模拟一个点击操作即可. 
    let tabSession = document.querySelector('.tab .tab-session');
    tabSession.click();
}

function findSessionByName(username) {
    // 先获取到会话列表中所有的 li 标签
    // 然后依次遍历, 看看这些 li 标签谁的名字和要查找的名字一致. 
    let sessionLis = document.querySelectorAll('#session-list>li');
    for (let sessionLi of sessionLis) {
        // 获取到该 li 标签里的 h3 标签, 进一步得到名字
        let h3 = sessionLi.querySelector('h3');
        if (h3.innerHTML == username) {
            return sessionLi;
        }
    }
    return null;
}

function createSession(friendId,id,sessionLi) {
    $.ajax({
        type: "post",
        url: "/session/addSession?toUserId=" + friendId + "&userId=" + id,
        success: function(result) {
            if(result != null && result.code == "SUCCESS") {
                let body = result.data;
                console.log("会话创建成功! sessionId = " + body.sessionId);
                sessionLi.setAttribute('message-session-id', body.sessionId);
            }else {
                alert(result.errMsg);
            }
        },
        error: function() {
            console.log('会话创建失败!');
        }
    })
}